//
// Created by Administrator on 2024/10/30.
//


#include "DcmToolkit.h"

void DcmToolKit::printTags(const std::string &filename) {
    DcmFileFormat dicomFile;
    if (dicomFile.loadFile(filename.c_str()).bad()) {
        throw std::runtime_error("read dicom file fail ");
    }
    dicomFile.print(std::cout);
    std::cout << OFendl;

}


std::map<std::string, std::string>
DcmToolKit::findTags(const std::string &filename, const std::vector<DcmTagKey> &tags,std::string &hospCode) {
    DcmFileFormat dicomFile;
    if (dicomFile.loadFile(filename.c_str()).bad()) {
        throw std::runtime_error("read dicom file fail ");
    }
    std::map<std::string, std::string> values;
    values.insert({"fileName", filename});
    DcmDataset *dataset = dicomFile.getDataset();

    for (const auto &tagKey: tags) {
        std::string value;
        if (dataset->findAndGetOFString(tagKey, value).good()) {
            values.insert({DcmTag(tagKey).getTagName(), value});
        }
        if (tagKey == DCM_TransferSyntaxUID) {
            DcmMetaInfo *meta = dicomFile.getMetaInfo();
            values.insert({DcmTag(tagKey).getTagName(), DcmXfer(meta->getOriginalXfer()).getXferID()});
        }
    }

    values.insert({"fileName", filename});
    values.insert({"storagePrefix", getObjKeyByPretzelProtocol(values)});
    values.insert({"installCode", "999999"});
    values.insert({"pipeline", hospCode});


    return values;
}


std::string DcmToolKit::getObjKeyByPrefix(std::map<std::string, std::string> dict) {
    auto studyDate = dict.at("StudyDate");
    if (studyDate.size() != 8) {
        throw std::runtime_error("study_date should be in the format YYYYMMDD");
    }

    std::string year = studyDate.substr(0, 4);
    std::string month = studyDate.substr(4, 2);
    std::string day = studyDate.substr(6, 2);
    auto stID = dict.at("StudyInstanceUID");
    auto trSID = dict.at("TransferSyntaxUID");
    return   std::format("ai-pacs/dicom/{}/{}/{}/{}/{}",year,month,day,stID,trSID);
}

std::string DcmToolKit::getObjKeyByPretzelProtocol(std::map<std::string, std::string> dict) {
    auto seID = dict.at("SeriesInstanceUID");
    auto sopID = dict.at("SOPInstanceUID");
    auto prefix = DcmToolKit::getObjKeyByPrefix(dict);
    return  std::format("{}/{}/{}.dcm",prefix,seID,sopID);
}

Promise<std::map<std::string, std::string>> DcmToolKit::Gather(std::vector<std::string> files,std::string &hospCode) {
    auto pp = co_await Awaiter<Promise<std::map<std::string, std::string>>::promise_type>{};
    for (const auto &file: files) {
        pp->value_ = DcmToolKit::findTags(file, REQUIRED_TAGS,hospCode);
        co_await std::suspend_always{};
    }
}

std::vector<std::map<std::string, std::string>> DcmToolKit::Executor(std::vector<std::string> &files,std::string &hospCode) {
    std::vector<std::map<std::string, std::string>> tmp_files;
    std::coroutine_handle<Promise<std::map<std::string, std::string>>::promise_type> handler = DcmToolKit::Gather(
            files,hospCode);
    Promise<std::map<std::string, std::string>>::promise_type &promise = handler.promise();
    for (auto file: files) {
        tmp_files.emplace_back(promise.value_);
        handler();
    }

    return tmp_files;
}
